namespace SharpTalk.Client.WpfApplication.Converters
{
    using System;
    using System.Globalization;
    using System.IO;
    using System.Windows;
    using System.Windows.Data;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;

    [ValueConversion(typeof(byte[]), typeof(BitmapImage))]
    public class BinaryToBitmapImageConverter : IValueConverter
    {
        private const string DEFAULT_URI = "/Images/default_user_32.png";

        /// <summary>
        /// Converts a value. 
        /// </summary>
        /// <returns>
        /// A converted value. If the method returns null, the valid null value is used.
        /// </returns>
        /// <param name="value">The value produced by the binding source.</param><param name="targetType">The type of the binding target property.</param><param name="parameter">The converter parameter to use.</param><param name="culture">The culture to use in the converter.</param>
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null) 
                return new BitmapImage(new Uri(DEFAULT_URI, UriKind.RelativeOrAbsolute));

            var bi = new BitmapImage();
            bi.BeginInit();
            bi.StreamSource = new MemoryStream((byte[])value);
            bi.EndInit();

            return bi;
        }
        /// <summary>
        /// Converts a value. 
        /// </summary>
        /// <returns>
        /// A converted value. If the method returns null, the valid null value is used.
        /// </returns>
        /// <param name="value">The value that is produced by the binding target.</param><param name="targetType">The type to convert to.</param><param name="parameter">The converter parameter to use.</param><param name="culture">The culture to use in the converter.</param>
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null) return value;
            var source = (BitmapImage)value;

            byte[] bits = null;
            using (var ms = new MemoryStream())
            {
                var encoder = new PngBitmapEncoder();
                var frame = BitmapFrame.Create(source);
                if (frame.Width > 48 || frame.Height > 48)
                    frame = Resize(frame, 48, 48, BitmapScalingMode.HighQuality);

                encoder.Frames.Add(frame);
                encoder.Interlace = PngInterlaceOption.On;
                encoder.Save(ms);
                bits = ms.GetBuffer();
            }
            return bits;
        }

        private static BitmapFrame Resize(ImageSource source, int width, int height, BitmapScalingMode scalingMode)
        {
            var group = new DrawingGroup();
            RenderOptions.SetBitmapScalingMode(group, scalingMode);
            group.Children.Add(new ImageDrawing(source, new Rect(0, 0, width, height)));

            var targetVisual = new DrawingVisual();
            var targetContext = targetVisual.RenderOpen();
            targetContext.DrawDrawing(group);
            var target = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Default);
            targetContext.Close();
            target.Render(targetVisual);
            var targetFrame = BitmapFrame.Create(target);
            return targetFrame;
        }
    }
}